#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#ifdef WIN32
#include "windows.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include "BList.h"
#include "BVector.h"
#include "geometrics.h"
#include "quaternion.h"
#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"

#include "AWLocalViewport.h"

#include "AWEntity.h"
#include "AWMessage.h"
#include "AWScenario.h"
#include "AWSelectScenario.h"
#include "AWBody.h"
#include "AWSensor.h"
#include "AWBrain.h"
#include "AWAgent.h"
#include "AWWorld.h"
#include "AWSelectWorld.h"
#include "AWViewMessageSelectWorld.h"


#include "loader.h"

extern int SCREEN_DX,SCREEN_DY;

AW_ViewMessageSelectWorld::AW_ViewMessageSelectWorld(void) : AW_SelectWorld()
{
	class_name->set("AW_ViewMessageSelectWorld");

	speedfact=4.0;

} /* AW_ViewMessageSelectWorld::AW_ViewMessageSelectWorld */ 


AW_ViewMessageSelectWorld::AW_ViewMessageSelectWorld(FILE *fp)  : AW_SelectWorld()
{
	class_name->set("AW_ViewMessageSelectWorld");

	speedfact=4.0;
	
	load(fp);
} /* AW_ViewMessageSelectWorld::AW_ViewMessageSelectWorld */ 


bool AW_ViewMessageSelectWorld::load(FILE *fp)
{
	int i,n_msg;
	AW_Message *m;
	Vector *v,*d;

	if (!AW_SelectWorld::load(fp)) return false;
	if (1!=fscanf(fp,"%f",&speedfact)) return false;
	if (1!=fscanf(fp,"%i",&n_msg)) return false;
	/* Leer mensages "in-progress": */ 
	for(i=0;i<n_msg;i++) {
		m=new AW_Message(fp);
		v=new Vector(fp);
		d=new Vector(fp);
		message_in_progress.Add(m);
		message_pos.Add(v);
		message_direction.Add(d);
	} /* for */ 
	return true;
} /* AW_ViewMessageSelectWorld::load */ 


bool AW_ViewMessageSelectWorld::save(FILE *fp)
{
	Vector *v,*d;
	AW_Message *m;

	if (!AW_SelectWorld::save(fp)) return false; 
	fprintf(fp,"%f\n",speedfact);
	fprintf(fp,"%i\n",message_pos.Length());
	/* Mensajes: */ 
	message_in_progress.Rewind();
	message_pos.Rewind();
	message_direction.Rewind();
	while(message_in_progress.Iterate(m)) {
		message_pos.Iterate(v);
		message_direction.Iterate(d);
		m->save(fp);
		v->save(fp);
		d->save(fp);
	} /* while */ 
	
	return true;
} /* AW_ViewMessageSelectWorld::save */ 


void AW_ViewMessageSelectWorld::beforedraw(void)
{
	if (camera_moving) {
		long current=GetTickCount();
		double t=(current-camera_move_start)/1000.0;
		if (t>=1.0) {
			camera=desired_camera;
			camerap=desired_camerap;
			camera_moving=false;
			if (desired_SelectedAgent!=0) {
				if (SelectedAgent!=0) delete SelectedAgent;
				SelectedAgent=desired_SelectedAgent;
				desired_SelectedAgent=0;
			} /* if */ 
		} else {
			camera.x=camera_move_A.x*t*t+camera_move_B.x*t+camera_move_C.x;
			camera.y=camera_move_A.y*t*t+camera_move_B.y*t+camera_move_C.y;
			camera.z=camera_move_A.z*t*t+camera_move_B.z*t+camera_move_C.z;

			camerap.x=camerap_move_A.x*t*t+camerap_move_B.x*t+camerap_move_C.x;
			camerap.y=camerap_move_A.y*t*t+camerap_move_B.y*t+camerap_move_C.y;
			camerap.z=camerap_move_A.z*t*t+camerap_move_B.z*t+camerap_move_C.z;
		} /* if */ 
	} /* if */ 

	AW_SelectWorld::beforedraw();
} /* AW_ViewMessageSelectWorldAW_ViewMessageSelectWorld::beforedraw */ 


void AW_ViewMessageSelectWorld::draw_world(void)
{
	Vector *v,*d;

	{
		AW_Agent *a,*local_agent=0;
		int name=0;

		if (scn->is_a("AW_SelectScenario")) {
			((AW_SelectScenario *)scn)->selection_first_name(0);
			scn->draw();
			name=((AW_SelectScenario *)scn)->selection_get_num();
		} else {
			scn->draw();
		} /* if */ 

		Agents.Rewind();
		while(Agents.Iterate(a)) {
			if (SelectedAgent!=0 && SelectedAgent->cmp(a->get_AgentName())) {
				local_agent=a;
			} else {
				glPushName(name);
				a->draw();
				glPopName();
			} /* if */ 
			name++;
		} /* while */ 
        
		if (local_agent!=0) local_agent->localdraw();
	}

	/* Mensajes: */ 
	message_pos.Rewind();
	message_direction.Rewind();
	while(message_pos.Iterate(v)) {
		message_direction.Iterate(d);
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glTranslatef(float(v->x),float(v->y)-0.5F,float(v->z));
		glColor3f(0.0,0.0,0.2F);
		glutSolidSphere(0.2F,16,16);
		glPopMatrix();
	} /* while */ 

} /* AW_ViewMessageSelectWorld::draw */ 


void AW_ViewMessageSelectWorld::actualize(float time,float timeinc)
{
	AW_Agent *a;
	AW_Message *m;
	Vector *v,*d,pos;
	double dx,dy,dz,n;
	double speed=speedfact*timeinc;

	AW_SelectWorld::actualize(time,timeinc);

	message_in_progress.Rewind();
	message_pos.Rewind();
	message_direction.Rewind();

	while(message_in_progress.Iterate(m)) {
		message_pos.Iterate(v);
		message_direction.Iterate(d);
		a=FindAgent(m->receiver);
		if (a!=0) {
			pos=a->get_pos();
			dx=pos.x-v->x;
			dy=pos.y-v->y;
			dz=pos.z-v->z;
			n=float(sqrt(dx*dx+dy*dy+dz*dz));
			if (n>speed) {
				dx/=n;
				dy/=n;
				dz/=n;
				dx*=speed;
				dy*=speed;
				dz*=speed;
				v->x+=dx;
				v->y+=dy;
				v->z+=dz;
				d->x=dx;
				d->y=dy;
				d->z=dz;
			} else {
				*v=pos;
//				write_debug_report("AW_ViewMessageSelectWorld: message delivered from %s to %s (size %i)\n",m->sender->get(),m->receiver->get(),strlen(m->content->get()));
				a->receive_msg(m);
				message_in_progress.DeleteElement(m);
				message_pos.DeleteElement(v);
				message_direction.DeleteElement(d);
			} /* if */ 
		} /* if */ 

	} /* while */ 

} /* AW_ViewMessageSelectWorld::actualize */ 


void AW_ViewMessageSelectWorld::sendmessage(AW_Message *m)
{
	AW_Agent *a;
	Vector v;

	a=FindAgent(m->sender);
	message_in_progress.Add(m);
	v=a->get_pos();

	if (!m->sender->cmp(m->receiver)) {
		/* Mensaje normal: */ 
		message_pos.Add(new Vector(v.x,v.y,v.z));
		message_direction.Add(new Vector(0,0,0));
	} else {
		/* Automensaje: */ 
		message_pos.Add(new Vector(0,v.y-10.0F,0));
		message_direction.Add(new Vector(0,0,0));
	} /* if */ 

} /* AW_ViewMessageSelectWorld::sendmessage */ 


bool AW_ViewMessageSelectWorld::is_a(char *c)
{
	if (strcmp(c,"AW_ViewMessageSelectWorld")==0) return true;

	return AW_SelectWorld::is_a(c);
} /* AW_ViewMessageSelectWorld::is_a */ 


bool AW_ViewMessageSelectWorld::is_a(Symbol *c)
{
	if (c->cmp("AW_ViewMessageSelectWorld")) return true;

	return AW_SelectWorld::is_a(c);
} /* AW_ViewMessageSelectWorld::is_a */ 


